package com.ymatou.iapi.settlement.testcase;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.stream.Collectors;

import org.apache.commons.collections.CollectionUtils;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.experimental.categories.Category;

import com.ymatou.i.accounting.api.parameter.AccountBean;
import com.ymatou.iapi.settlement.parameter.AdRateInfoPo;
import com.ymatou.iapi.settlement.parameter.AdRateProductInfo;
import com.ymatou.iapi.settlement.parameter.CheckAdCostReq;
import com.ymatou.iapi.settlement.parameter.GenerateAdRateInfoReq;
import com.ymatou.iapi.settlement.service.CheckAdCostCall;
import com.ymatou.iapi.settlement.service.GenerateAdRateInfoCall;
import com.ymatou.iapi.trading.operate.parameter.Order;
import com.ymatou.iapi.trading.operate.parameter.OrderInfoPo;
import com.ymatou.iapi.trading.operate.parameter.OrderItemVo;
import com.ymatou.iapi.trading.operate.parameter.PlaceOrderResp;
import com.ymatou.iapi.trading.operate.parameter.PlaceOrderService;
import com.ymatou.iapi.trading.operate.parameter.req.PlaceOrderReq;
import com.ymatou.iapi.trading.ordersync.service.SyncVerifyService;
import com.ymt.core.tool.Logger;
import com.ymt.utils.annotation.TestCase;
import com.ymt.utils.annotation.TestSuite;
import com.ymt.utils.tag.P1;
import com.ymttest.business.service.OrderCallService;
import com.ymttest.common.enums.CancelOrderTypeEnum;
import com.ymttest.database.model.YmtSettlementInvoice;
import com.ymttest.database.sqlwapper.DefaultWapper;
import com.ymttest.database.sqlwapper.YmtSettlementInvoiceWapper;
import com.ymttest.utils.DataUtil;
import com.ymttest.utils.EnvSetup;
import com.ymttest.utils.TestDataManager;

/**
 * 对广告费结算单判断是否需要收费接口 FreeMaker Template自动生成代码
 */
@TestSuite
public class Ts_CheckAdCost {
	private static CheckAdCostReq checkAdCostReq;
	private static CheckAdCostCall checkAdCostCall;

	private static Map<Integer, AccountBean> mapAccount;
	private static int sellerId = Integer.valueOf(EnvSetup.getData("BuyerId"));
	private static YmtSettlementInvoiceWapper ymtSettlementInvoiceWapper = new YmtSettlementInvoiceWapper();

	@BeforeClass
	public static void setUp() {
		Logger.createResultFile("对广告费结算单判断是否需要收费接口");
	}

	@Before
	public void caseUp() {

	}
	@AfterClass
	public static void tearDown() {
		Logger.generateResult(checkAdCostCall.getOpurl());
	}

	@After
	public void caseDown() {
		Logger.end();
	}

	/**
	 * 
	 * 根据商品productid 下单,一个订单下面2个商品，其中一个商品指定produnctid
	 * 
	 */
	public static PlaceOrderResp placeOrder(List<String> proIds) {

		PlaceOrderReq placeorderBean = PlaceOrderService.getDefaultOrderReq();

		OrderItemVo orderitem2 = PlaceOrderService.getDefaultOrderItemVo();

		placeorderBean.getOrderGroups().get(0).getOrders().get(0)
				.getOrderItems().add(orderitem2);

		List<OrderItemVo> orderItemList = placeorderBean.getOrderGroups()
				.get(0).getOrders().get(0).getOrderItems();

		if (!CollectionUtils.isEmpty(proIds)) {

			for (int i = 0; i < orderItemList.size(); i++) {

				if (proIds.size() > i) {

					orderItemList.get(i).setProductId(proIds.get(i));

				}
			}

		}

		return PlaceOrderService.callPlaceOrderService(placeorderBean);

	}

	/**
	 * 订单下所有商品都收取广告费
	 * @param orderId
	 * @param orderInfoList
	 */
	private void callGenerateAdRateInfo(int orderId,
			List<OrderInfoPo> orderInfoList) {

		GenerateAdRateInfoReq generateAdRateInfoReq = new GenerateAdRateInfoReq();
		GenerateAdRateInfoCall generateAdRateInfoCall = new GenerateAdRateInfoCall();

		List<AdRateProductInfo> list = new ArrayList<AdRateProductInfo>();

		orderInfoList
				.forEach(orderInfo -> {

					BigDecimal adCostMax = new BigDecimal(1 + new Random()
							.nextInt(30));

					AdRateProductInfo adRateProductInfo = new AdRateProductInfo();

					adRateProductInfo.setProductId(orderInfo.getProductId());

					adRateProductInfo.setAdId(TestDataManager
							.getRandomIntNum(9));

					adRateProductInfo.setAdCostId(TestDataManager
							.getRandomUUID().toString());

					adRateProductInfo.setAdRate(new BigDecimal(new Random()
							.nextFloat() / 10));

					adRateProductInfo.setAdCostMax(adCostMax);

					list.add(adRateProductInfo);

				});

		generateAdRateInfoReq.setOrderId(orderId);

		generateAdRateInfoReq.setAdProductInfos(list);

		generateAdRateInfoCall.setData(false, generateAdRateInfoReq);

		try {
			generateAdRateInfoCall.callService();

		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

	public static void callCheckAdCost() throws Exception {

		checkAdCostReq = new CheckAdCostReq();
		checkAdCostCall = new CheckAdCostCall();

		checkAdCostReq.setNum(150);

		checkAdCostCall.setData(checkAdCostReq);

		checkAdCostCall.callService();

	}

	private void verifyDb2(int userId, int sellerId, int orderId,
			List<String> proList) {

		List<Map> list;

		try {

			Thread.sleep(3000);

			list = new DefaultWapper().getAdOrderInfo(userId, sellerId,
					orderId, proList);

			Map<String, Integer> m = new HashMap<String, Integer>();;

			for (Map map : list) {

				m.put((String) map.get("sProductId"), (Integer) map.get("oid"));

			}

			List<AdRateInfoPo> adRateInfoPoList = new YmtSettlementInvoiceWapper()

			.selectYmtAdRateInfo(orderId);

			Logger.comment(String.format("校验订单 %s,Ymt_AdRateInfo ", orderId));

			adRateInfoPoList.forEach(ad -> {

				if (m.containsKey(ad.getProductId())) {

					Logger.comment(String.format("Ymt_AdRateInfo productId:"
							+ " %s ", ad.getProductId()));

					Logger.verifyEquals(Long.valueOf(m.get(ad.getProductId())),
							ad.getRelatedCancelId(),
							"校验Ymt_AdRateInfo RelatedCancelId");

				} else {
					Logger.verifyEquals(null, ad.getRelatedCancelId(),
							"校验Ymt_AdRateInfo RelatedCancelId");
				}

			});

			Map map = new HashMap();

			map.put("orderId", orderId);
			map.put("businessType", 13);

			List<YmtSettlementInvoice> ymtSettlementInvoiceList = new YmtSettlementInvoiceWapper()
					.selectYmtSettlementInvoice(map);

			BigDecimal expectSettlementAmount = adRateInfoPoList.stream()
					.filter(ad -> ad.getRelatedCancelId() == null)
					.map(ad -> ad.getCostAmount())
					.reduce(BigDecimal.ZERO, BigDecimal::add);

			DataUtil.verifyDecimalEquals(expectSettlementAmount,
					ymtSettlementInvoiceList.get(0).getCashAmount(),
					"校验实际结算的广告费用");

		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}
	@Test
	@Category({P1.class})
	@TestCase
	public void Tc_CheckAdCost_000() {
		Logger.start(true, "test");

		try {
			callCheckAdCost();

		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	@Test
	@Category({P1.class})
	@TestCase
	public void Tc_CheckAdCost_001() {
		Logger.start(true, "一个订单多个广告商品,其中一个商品24小时内有订单支付后取消记录");
		try {

			PlaceOrderResp placeOrderResp = PlaceOrderService.placeOrder4();

			Order order = placeOrderResp.getOrderList().get(0);

			int sellerId = order.getSellerId();

			int orderId = order.getOrderId();
			int userId = placeOrderResp.getUserId();
			int traidngId = placeOrderResp.getTradingId();
			BigDecimal payAmount = placeOrderResp.getPayAmount();

			new OrderCallService()
					.orderPayRequest(userId, payAmount, traidngId);

			new OrderCallService().cancelOrder(orderId, userId,
					CancelOrderTypeEnum.BuyerCancelOrder);

			callGenerateAdRateInfo(orderId, order.getOrderInfoList());

			List<String> proIds = Arrays.asList(order.getOrderInfoList().get(0)
					.getProductId());

			//根据商品id 下单
			PlaceOrderResp placeOrderResp2 = placeOrder(proIds);

			Order order2 = placeOrderResp2.getOrderList().get(0);

			int orderId2 = order2.getOrderId();
			int traidngId2 = placeOrderResp2.getTradingId();
			BigDecimal payAmount2 = placeOrderResp2.getPayAmount();

			new OrderCallService().orderPayRequest(userId, payAmount2,
					traidngId2);

			SyncVerifyService.getSyncResult(orderId2);

			callGenerateAdRateInfo(orderId2, order2.getOrderInfoList());

			List<String> proList = new ArrayList<String>();
			order.getOrderInfoList().forEach(
					item -> proList.add(item.getProductId()));

			callCheckAdCost();

			verifyDb2(userId, sellerId, orderId2, proList);

		} catch (Exception e) {
			Logger.fail(e);
		}
	}
	@Test
	@Category({P1.class})
	@TestCase
	public void Tc_CheckAdCost_002() {
		Logger.start(true, "一个订单多个广告商品,24小时内有订单所有商品都有支付后取消记录");
		try {

			PlaceOrderResp placeOrderResp = PlaceOrderService.placeOrder4();

			Order order = placeOrderResp.getOrderList().get(0);

			int sellerId = order.getSellerId();

			int orderId = order.getOrderId();
			int userId = placeOrderResp.getUserId();
			int traidngId = placeOrderResp.getTradingId();
			BigDecimal payAmount = placeOrderResp.getPayAmount();

			new OrderCallService()
					.orderPayRequest(userId, payAmount, traidngId);

			new OrderCallService().cancelOrder(orderId, userId,
					CancelOrderTypeEnum.BuyerCancelOrder);

			//等待同步
			SyncVerifyService.getSyncResult(orderId);

			//生成广告费结算
			callGenerateAdRateInfo(orderId, order.getOrderInfoList());

			List<String> proIds = order.getOrderInfoList().stream()
					.map(item -> item.getProductId())
					.collect(Collectors.toList());

			PlaceOrderResp placeOrderResp2 = placeOrder(proIds);

			Order order2 = placeOrderResp2.getOrderList().get(0);

			int orderId2 = order2.getOrderId();
			int traidngId2 = placeOrderResp2.getTradingId();
			BigDecimal payAmount2 = placeOrderResp2.getPayAmount();

			new OrderCallService().orderPayRequest(userId, payAmount2,
					traidngId2);

			//等待同步
			SyncVerifyService.getSyncResult(orderId2);

			callGenerateAdRateInfo(orderId2, order2.getOrderInfoList());

			List<String> proList = new ArrayList<String>();

			order2.getOrderInfoList().forEach(
					item -> proList.add(item.getProductId()));

			callCheckAdCost();

			verifyDb2(userId, sellerId, orderId2, proList);

		} catch (Exception e) {
			Logger.fail(e);
		}
	}
	@Test
	@Category({P1.class})
	@TestCase
	public void Tc_CheckAdCost_003() {
		Logger.start(true,
				"一个订单多个广告商品,a,b 2个商品，第一单a商品订单取消，第二单b商品订单取消，第三笔a,b 商品支付,校验第三笔广告费结算");
		try {

			//第一单
			PlaceOrderResp placeOrderResp = PlaceOrderService.placeOrder4();

			Order order = placeOrderResp.getOrderList().get(0);

			int sellerId = order.getSellerId();

			int orderId = order.getOrderId();
			int userId = placeOrderResp.getUserId();
			int traidngId = placeOrderResp.getTradingId();
			BigDecimal payAmount = placeOrderResp.getPayAmount();

			new OrderCallService()
					.orderPayRequest(userId, payAmount, traidngId);

			new OrderCallService().cancelOrder(orderId, userId,
					CancelOrderTypeEnum.BuyerCancelOrder);

			//等待同步
			SyncVerifyService.getSyncResult(orderId);

			callGenerateAdRateInfo(orderId, order.getOrderInfoList());

			//第2笔
			List<String> proIds = Arrays.asList(order.getOrderInfoList().get(1)
					.getProductId());

			//根据商品id 下单
			PlaceOrderResp placeOrderResp2 = placeOrder(proIds);

			Order order2 = placeOrderResp2.getOrderList().get(0);

			int orderId2 = order2.getOrderId();
			int traidngId2 = placeOrderResp2.getTradingId();
			BigDecimal payAmount2 = placeOrderResp2.getPayAmount();

			new OrderCallService().orderPayRequest(userId, payAmount2,
					traidngId2);

			new OrderCallService().cancelOrder(orderId2, userId,
					CancelOrderTypeEnum.BuyerCancelOrder);

			//等待同步
			SyncVerifyService.getSyncResult(orderId2);

			callGenerateAdRateInfo(orderId2, order2.getOrderInfoList());

			//第三笔

			String aproId = placeOrderResp.getOrderList().get(0)
					.getOrderInfoList().get(0).getProductId();

			String bproId = placeOrderResp2.getOrderList().get(0)
					.getOrderInfoList().get(1).getProductId();

			PlaceOrderResp placeOrderResp3 = placeOrder(Arrays.asList(aproId,
					bproId));

			Order order3 = placeOrderResp3.getOrderList().get(0);

			int orderId3 = order3.getOrderId();
			int traidngId3 = placeOrderResp3.getTradingId();
			BigDecimal payAmount3 = placeOrderResp3.getPayAmount();

			new OrderCallService().orderPayRequest(userId, payAmount3,
					traidngId3);

			SyncVerifyService.getSyncResult(orderId3);

			callGenerateAdRateInfo(orderId3, order3.getOrderInfoList());

			List<String> proList = new ArrayList<String>();

			order3.getOrderInfoList().forEach(
					item -> proList.add(item.getProductId()));

			callCheckAdCost();

			Logger.comment("第一单：" + orderId);
			Logger.comment("第二单：" + orderId2);
			Logger.comment("第三单：" + orderId3);

			verifyDb2(userId, sellerId, orderId3, proList);

		} catch (Exception e) {
			Logger.fail(e);
		}
	}
	@Test
	@Category({P1.class})
	@TestCase
	public void Tc_CheckAdCost_004() {
		Logger.start(true,
				"一个订单多个广告商品,a,b 2个商品，第一单a商品订单取消，第二单b商品订单取消，第三笔a,b 商品支付,校验第三笔广告费结算");
		try {
			//第一单
			PlaceOrderResp placeOrderResp = PlaceOrderService.placeOrder4();

			Order order = placeOrderResp.getOrderList().get(0);

			int sellerId = order.getSellerId();

			int orderId = order.getOrderId();
			int userId = placeOrderResp.getUserId();
			int traidngId = placeOrderResp.getTradingId();
			BigDecimal payAmount = placeOrderResp.getPayAmount();

			new OrderCallService()
					.orderPayRequest(userId, payAmount, traidngId);

			new OrderCallService().cancelOrder(orderId, userId,
					CancelOrderTypeEnum.BuyerCancelOrder);

			callGenerateAdRateInfo(orderId, order.getOrderInfoList());

			//第2笔
			List<String> proIds = Arrays.asList(order.getOrderInfoList().get(1)
					.getProductId());

			//根据商品id 下单
			PlaceOrderResp placeOrderResp2 = placeOrder(proIds);

			Order order2 = placeOrderResp2.getOrderList().get(0);

			int orderId2 = order2.getOrderId();
			int traidngId2 = placeOrderResp2.getTradingId();
			BigDecimal payAmount2 = placeOrderResp2.getPayAmount();

			new OrderCallService().orderPayRequest(userId, payAmount2,
					traidngId2);

			new OrderCallService().cancelOrder(orderId2, userId,
					CancelOrderTypeEnum.BuyerCancelOrder);

			//等待同步
			SyncVerifyService.getSyncResult(orderId2);

			callGenerateAdRateInfo(orderId2, order2.getOrderInfoList());

			//第三笔

			String aproId = placeOrderResp.getOrderList().get(0)
					.getOrderInfoList().get(0).getProductId();

			String bproId = proIds.get(0);

			PlaceOrderResp placeOrderResp3 = placeOrder(Arrays.asList(aproId,
					bproId));

			Order order3 = placeOrderResp3.getOrderList().get(0);

			int orderId3 = order3.getOrderId();
			int traidngId3 = placeOrderResp3.getTradingId();
			BigDecimal payAmount3 = placeOrderResp3.getPayAmount();

			new OrderCallService().orderPayRequest(userId, payAmount3,
					traidngId3);

			//等待同步
			SyncVerifyService.getSyncResult(orderId3);

			callGenerateAdRateInfo(orderId3, order3.getOrderInfoList());

			List<String> proList = new ArrayList<String>();

			order3.getOrderInfoList().forEach(
					item -> proList.add(item.getProductId()));

			callCheckAdCost();

			Logger.comment("第一单：" + orderId);
			Logger.comment("第二单：" + orderId2);
			Logger.comment("第三单：" + orderId3);

			verifyDb2(userId, sellerId, orderId3, proList);

		} catch (Exception e) {
			Logger.fail(e);
		}
	}
	@Test
	@Category({P1.class})
	@TestCase
	public void Tc_CheckAdCost_005() {
		Logger.start(true, "一个订单多个广告商品,其中一个商品24小时内有订单支付后取消记录,但未结算广告费。当前这笔正常结算");
		try {

			PlaceOrderResp placeOrderResp = PlaceOrderService.placeOrder4();

			Order order = placeOrderResp.getOrderList().get(0);

			int sellerId = order.getSellerId();

			int orderId = order.getOrderId();
			int userId = placeOrderResp.getUserId();
			int traidngId = placeOrderResp.getTradingId();
			BigDecimal payAmount = placeOrderResp.getPayAmount();

			new OrderCallService()
					.orderPayRequest(userId, payAmount, traidngId);

			new OrderCallService().cancelOrder(orderId, userId,
					CancelOrderTypeEnum.BuyerCancelOrder);

			//callGenerateAdRateInfo(orderId, order.getOrderInfoList());

			List<String> proIds = Arrays.asList(order.getOrderInfoList().get(0)
					.getProductId());

			//根据商品id 下单
			PlaceOrderResp placeOrderResp2 = placeOrder(proIds);

			Order order2 = placeOrderResp2.getOrderList().get(0);

			int orderId2 = order2.getOrderId();
			int traidngId2 = placeOrderResp2.getTradingId();
			BigDecimal payAmount2 = placeOrderResp2.getPayAmount();

			new OrderCallService().orderPayRequest(userId, payAmount2,
					traidngId2);

			SyncVerifyService.getSyncResult(orderId2);

			callGenerateAdRateInfo(orderId2, order2.getOrderInfoList());

			List<String> proList = new ArrayList<String>();
			order.getOrderInfoList().forEach(
					item -> proList.add(item.getProductId()));

			callCheckAdCost();

			Logger.comment("第一单：" + orderId);
			Logger.comment("第二单：" + orderId2);

			verifyDb2(userId, sellerId, orderId2, proList);

		} catch (Exception e) {
			Logger.fail(e);
		}
	}
}
